package com.zzl.alligator.management.monitor.service.impl;


import com.zzl.alligator.common.constant.SystemConstants;
import com.zzl.alligator.framework.job.listener.JobLogListener;
import com.zzl.alligator.management.monitor.domain.QrtzJobDetails;
import com.zzl.alligator.management.monitor.mapper.QrtzJobDetailsMapper;
import com.zzl.alligator.management.monitor.service.IQrtzJobDetailsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.matchers.EverythingMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
/**
 * (QrtzJobDetails)服务层
 *
 * @author zhouziliang
 * @since 2020-07-10
 */
@Service
@Slf4j
public class QrtzJobDetailsService implements IQrtzJobDetailsService {
    
    @Autowired
    private QrtzJobDetailsMapper qrtzJobDetailsMapper;
    @Autowired
    private Scheduler scheduler;

    @PostConstruct
    public void init() throws SchedulerException {
        scheduler.getListenerManager().addJobListener(new JobLogListener(), EverythingMatcher.allJobs());
    }
    /**
     * 通过ID查询单条数据
     *
     * @param jobName 主键
     * @param jobGroup 组
     * @return 实例对象
     */
    @Override
    public QrtzJobDetails findQrtzJobDetailsById(String jobName, String jobGroup) throws SchedulerException {
        return fillJob(qrtzJobDetailsMapper.findQrtzJobDetailsById(jobName, jobGroup));
    }

   /**
     * 通过实体作为筛选条件查询
     *
     * @param qrtzJobDetails 实例对象
     * @return 对象列表
     */
    @Override
    public List<QrtzJobDetails> findQrtzJobDetailsList(QrtzJobDetails qrtzJobDetails) throws SecurityException{
        List<QrtzJobDetails> qrtzJobDetailsList = qrtzJobDetailsMapper.findQrtzJobDetailsList(qrtzJobDetails);
        if (qrtzJobDetailsList != null) {
            qrtzJobDetailsList.stream().forEach(job -> {
                try {
                    fillJob(job);
                } catch (SchedulerException e) {
                    log.error("z执行失败", e);
                }
            });
        }
        return qrtzJobDetailsList;
    }

    /**
     * job增加执行方法信息
     *
     * @param job
     * @return
     */
    private QrtzJobDetails fillJob(QrtzJobDetails job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        JobDetail jobDetail = null;
        try {
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        job.setJobMethodName(jobDetail.getJobDataMap().getString("jobMethodName"));
        Date nextFireTime = scheduler.getTriggersOfJob(jobKey).get(0).getNextFireTime();
        job.setNextFireTime(nextFireTime);
        return job;
    }

    /**
     * 新增数据
     *
     * @param job 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(QrtzJobDetails job) throws SchedulerException, ClassNotFoundException, IllegalAccessException,
            InstantiationException {
        if (StringUtils.isNotBlank(job.getOldJobName())) {
            JobKey oldJobKey = new JobKey(job.getOldJobName(), job.getOldJobGroup());
            scheduler.deleteJob(oldJobKey);
        }
        Class clz = Class.forName(job.getJobClassName());
        clz.newInstance();
        JobDetail jobDetail = JobBuilder.newJob(clz)
                .withIdentity(job.getJobName(), job.getJobGroup())
                .withDescription(job.getDescription()).build();
        jobDetail.getJobDataMap().put("jobMethodName", job.getJobMethodName());
        jobDetail.getJobDataMap().put("methodParam", job.getJobMethodParam());
        // 触发时间点
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger:" + job.getJobName(), job.getJobGroup())
                .withSchedule(cronScheduleBuilder)
                .startNow()
                .build();

        //交由Scheduler安排触发
        scheduler.scheduleJob(jobDetail, trigger);

        if (SystemConstants.NO_FRAME.equals(job.getDealState())) {
            pause(job);
        }
    }

    /**
     * 恢复任务
     *
     * @param job
     * @throws SchedulerException
     */
    @Override
    public void resume(QrtzJobDetails job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        scheduler.resumeJob(jobKey);
    }

    /**
     * 暂停任务
     *
     * @param job
     * @throws SchedulerException
     */
    @Override
    public void pause(QrtzJobDetails job) throws SchedulerException {
        JobKey jobKey = new JobKey(job.getJobName(), job.getJobGroup());
        scheduler.pauseJob(jobKey);
    }

    /**
     * 单次执行任务
     *
     * @param qrtzJobDetails 任务信息
     */
    @Override
    public void run(QrtzJobDetails qrtzJobDetails) throws SchedulerException {
        log.info("触发任务：{}", qrtzJobDetails.getJobName());
        JobKey jobKey = new JobKey(qrtzJobDetails.getJobName(), qrtzJobDetails.getJobGroup());
        scheduler.triggerJob(jobKey);
    }

    /**
     * 删除任务
     *
     * @param jobGroup 任务组
     * @param jobName  任务名
     */
    @Override
    public void delete(String jobGroup, String jobName) throws SchedulerException {
        JobKey jobKey = new JobKey(jobName, jobGroup);
        scheduler.deleteJob(jobKey);
    }
}